package com.example.mychat.network

import android.util.Log
import kotlinx.coroutines.*
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.net.Socket

class ChatClient(
    private val serverAddress: String = "10.129.16.118",
    private val serverPort: Int = 9999,
    private var messageCallback: (String) -> Unit,
    private var onConnectionError: () -> Unit
) {
    private var socket: Socket? = null
    private var writer: PrintWriter? = null
    private var reader: BufferedReader? = null
    private var isRunning = false
    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
    private var receiveJob: Job? = null

    suspend fun connect(successCallBack: (() -> Unit)? = null, failureCallback: (() ->  Unit)? = null) = withContext(Dispatchers.IO) {
        try {
            Log.d("ChatClient", "正在连接服务器: $serverAddress:$serverPort")
            socket = Socket(serverAddress, serverPort)
            Log.d("ChatClient", "成功连接到服务器")
            
            writer = PrintWriter(socket!!.getOutputStream(), true).also {
                Log.d("ChatClient", "创建 writer 成功")
            }
            reader = BufferedReader(InputStreamReader(socket!!.getInputStream())).also {
                Log.d("ChatClient", "创建 reader 成功")
            }
            isRunning = true
            successCallBack?.invoke()
            startReceiving()
            true
        } catch (e: Exception) {
            Log.e("ChatClient", "连接失败: ${e.message}", e)
            failureCallback?.invoke()
            e.printStackTrace()
            onConnectionError()
            false
        }
    }

    private fun startReceiving() {
        receiveJob?.cancel()
        receiveJob = scope.launch {
            try {
                Log.d("ChatClient", "开始接收消息")
                while (isRunning && socket?.isConnected == true && !socket?.isClosed!!) {
                    try {
                        val message = reader?.readLine()
                        Log.d("ChatClient", "读取到消息: $message")
                        if (message != null) {
                            Log.d("ChatClient", "收到消息: $message")
                            withContext(Dispatchers.Main) {
                                messageCallback(message)
                            }
                        } else {
                            Log.d("ChatClient", "连接已关闭")
                            break
                        }
                    } catch (e: CancellationException) {
                        Log.d("ChatClient", "接收消息任务被取消")
                        throw e
                    } catch (e: Exception) {
                        Log.e("ChatClient", "读取消息时出错: ${e.message}", e)
                        if (isRunning) {
                            withContext(Dispatchers.Main) {
                                onConnectionError()
                            }
                        }
                        break
                    }
                }
            } catch (e: CancellationException) {
                Log.d("ChatClient", "接收消息协程被取消")
                throw e
            } catch (e: Exception) {
                Log.e("ChatClient", "接收消息失败: ${e.message}", e)
                e.printStackTrace()
                if (isRunning) {
                    withContext(Dispatchers.Main) {
                        onConnectionError()
                    }
                }
            } finally {
                Log.d("ChatClient", "接收消息循环结束")
            }
        }
    }

    suspend fun sendMessage(message: String) = withContext(Dispatchers.IO) {
        try {
            if (socket?.isConnected != true || socket?.isClosed == true) {
                throw Exception("Socket未连接或已关闭")
            }
            Log.d("ChatClient", "准备发送消息: $message")
            writer?.let { w ->
                w.println(message)
                w.flush()
                Log.d("ChatClient", "消息发送完成")
            } ?: throw Exception("Writer未初始化")
        } catch (e: CancellationException) {
            Log.d("ChatClient", "发送消息任务被取消")
            throw e
        } catch (e: Exception) {
            Log.e("ChatClient", "发送消息失败: ${e.message}", e)
            e.printStackTrace()
            onConnectionError()
            throw e
        }
    }

    fun disconnect() {
        isRunning = false
        scope.cancel() // 取消所有协程
        receiveJob?.cancel() // 取消接收消息的协程
        try {
            Log.d("ChatClient", "正在断开连接")
            writer?.close()
            reader?.close()
            socket?.close()
            Log.d("ChatClient", "连接已断开")
        } catch (e: Exception) {
            Log.e("ChatClient", "关闭连接失败: ${e.message}", e)
            e.printStackTrace()
        }
    }

    fun updateMessageCallback(
        messageCallback: (String) -> Unit,
        onConnectionError: () -> Unit
    ) {
        this.messageCallback = messageCallback
        this.onConnectionError = onConnectionError
    }
} 